<?php

    /**
     * Osclass – software for creating and publishing online classified advertising platforms
     *
     * Copyright (C) 2012 OSCLASS
     *
     * This program is free software: you can redistribute it and/or modify it under the terms
     * of the GNU Affero General Public License as published by the Free Software Foundation,
     * either version 3 of the License, or (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     * See the GNU Affero General Public License for more details.
     *
     * You should have received a copy of the GNU Affero General Public
     * License along with this program. If not, see <http://www.gnu.org/licenses/>.
     */

    define('DB_FUNC_NOW', 'NOW()');
    define('DB_CONST_TRUE', 'TRUE');
    define('DB_CONST_FALSE', 'FALSE');
    define('DB_CONST_NULL', 'NULL');
    define('DB_CUSTOM_COND', 'DB_CUSTOM_COND');
    /**
     * DAO base model
     * 
     * @package Osclass
     * @subpackage Model
     * @since 2.3
     */
    class DAO
    {
        /**
         * DBCommandClass object
         * 
         * @acces public
         * @since 2.3
         * @var DBCommandClass 
         */
        var $dao;
        /**
         * Table name
         * 
         * @access private
         * @since unknown
         * @var string 
         */
        var $tableName;
        /**
         * Table prefix
         * 
         * @access private
         * @since unknown
         * @var string 
         */
        var $tablePrefix;
        /**
         * Primary key of the table
         *
         * @access private
         * @since 2.3
         * @var string 
         */
        var $primaryKey;
        /**
         * Fields of the table
         * 
         * @access private
         * @since 2.3
         * @var array 
         */
        var $fields;

        /**
         * Init connection of the database and create DBCommandClass object
         */
        function __construct()
        {
            $conn              = DBConnectionClass::newInstance();
            $data              = $conn->getOsclassDb();
            $this->dao         = new DBCommandClass($data);
            $this->tablePrefix = DB_TABLE_PREFIX;
        }
        
        /**
         * Reinitialize connection to the database once the object is unserialized
         */
        public function __wakeup()
        {
            $conn              = DBConnectionClass::newInstance();
            $data              = $conn->getOsclassDb();
            $this->dao         = new DBCommandClass($data);
        }

        /**
         * Get the result match of the primary key passed by parameter
         * 
         * @access public
         * @since unknown
         * @param string $value
         * @return mixed If the result has been found, it return the array row. If not, it returns false
         */
        function findByPrimaryKey($value)
        {
            $this->dao->select($this->fields);
            $this->dao->from($this->getTableName());
            $this->dao->where($this->getPrimaryKey(), $value);
            $result = $this->dao->get();

            if( $result === false ) {
                return false;
            }

            if( $result->numRows() !== 1 ) {
                return false;
            }

            return $result->row();
        }

        /**
         * Update row by primary key
         * 
         * @access public
         * @since unknown
         * @param array $values Array with keys (database field) and values
         * @param string $key Primary key to be updated
         * @return mixed It return the number of affected rows if the update has been 
         * correct or false if nothing has been modified
         */
        function updateByPrimaryKey($values, $key)
        {
            $cond = array(
                $this->getPrimaryKey() => $key
            );

            return $this->update($values, $cond);
        }

        /**
         * Delete the result match from the primary key passed by parameter
         * 
         * @access public
         * @since unknown
         * @param string $value
         * @return mixed It return the number of affected rows if the delete has been 
         * correct or false if nothing has been modified
         */
        function deleteByPrimaryKey($value)
        {
            $cond = array(
                $this->getPrimaryKey() => $value
            );

            return $this->delete($cond);
        }

        /**
         * Get all the rows from the table $tableName
         * 
         * @access public
         * @since unknown
         * @return array 
         */
        function listAll()
        {
            $this->dao->select($this->getFields());
            $this->dao->from($this->getTableName());
            $result = $this->dao->get();

            if($result == false) {
                return array();
            }

            return $result->result();
        }

        /**
         * Basic insert
         * 
         * @access public
         * @since unknown
         * @param array $values
         * @return boolean 
         */
        function insert($values)
        {
            if( !$this->checkFieldKeys(array_keys($values)) ) {
                return false;
            }

            $this->dao->from($this->getTableName());
            $this->dao->set($values);
            return $this->dao->insert();
        }

        /**
         * Basic update. It returns false if the keys from $values or $where doesn't
         * match with the fields defined in the construct
         * 
         * @access public
         * @since unknown
         * @param array $values Array with keys (database field) and values
         * @param array $where
         * @return mixed It returns the number of affected rows if the update has been 
         * correct or false if an error happended
         */
        function update($values, $where)
        {
            if( !$this->checkFieldKeys(array_keys($values)) ) {
                return false;
            }

            if( !$this->checkFieldKeys(array_keys($where)) ) {
                return false;
            }

            $this->dao->from($this->getTableName());
            $this->dao->set($values);
            $this->dao->where($where);
            return $this->dao->update();
        }

        /**
         * Basic delete. It returns false if the keys from $where doesn't
         * match with the fields defined in the construct
         * 
         * @access public
         * @since unknown
         * @param array $where
         * @return mixed It returns the number of affected rows if the delete has been 
         * correct or false if an error happended
         */
        function delete($where)
        {
            if( !$this->checkFieldKeys(array_keys($where)) ) {
                return false;
            }

            $this->dao->from($this->getTableName());
            $this->dao->where($where);
            return $this->dao->delete();
        }

        /**
         * Set table name, adding the DB_TABLE_PREFIX at the beginning
         * 
         * @access private
         * @since unknown
         * @param string $table 
         */
        function setTableName($table)
        {
            $this->tableName = $this->tablePrefix . $table;
        }

        /**
         * Get table name
         * 
         * @access public
         * @since unknown
         * @return string 
         */
        function getTableName()
        {
            return $this->tableName;
        }

        /**
         * Set primary key string
         * 
         * @access private
         * @since unknown
         * @param string $key 
         */
        function setPrimaryKey($key)
        {
            $this->primaryKey = $key;
        }

        /**
         * Get primary key string
         * 
         * @access public
         * @since unknown
         * @return string 
         */
        function getPrimaryKey()
        {
            return $this->primaryKey;
        }

        /**
         * Set fields array
         * 
         * @access private
         * @since 2.3
         * @param array $fields 
         */
        function setFields($fields)
        {
            $this->fields = $fields;
        }

        /**
         * Get fields array
         * 
         * @access public
         * @since 2.3
         * @return array 
         */
        function getFields()
        {
            return $this->fields;
        }

        /**
         * Check if the keys of the array exist in the $fields array
         * 
         * @access private
         * @since 2.3
         * @param array $aKey
         * @return boolean 
         */
        function checkFieldKeys($aKey)
        {
            foreach($aKey as $key) {
                if( !in_array($key, $this->getFields()) ) {
                    return false;
                }
            }

            return true;
        }

        /**
         * Get table prefix
         * 
         * @access public
         * @since 2.3
         * @return string 
         */
        function getTablePrefix()
        {
            return $this->tablePrefix;
        }

        /**
         * Returns the last error code for the most recent mysqli function call
         * 
         * @access public
         * @since 2.3
         * @return int 
         */
        function getErrorLevel()
        {
            return $this->dao->getErrorLevel();
        }

        /**
         * Returns a string description of the last error for the most recent MySQLi function call
         * 
         * @access public
         * @since 2.3
         * @return string 
         */
        function getErrorDesc()
        {
            return $this->dao->getErrorDesc();
        }

        /**
         * Returns the number of rows in the table represented by this object.
         * 
         * @access public
         * @since unknown
         * @return int
         */
        public function count()
        {
            $this->dao->select('COUNT(*) AS count');
            $this->dao->from($this->getTableName());
            $result = $this->dao->get();

            if( $result == false ) {
                return 0;
            }

            if( $result->numRows() == 0 ) {
                return 0;
            }

            $row = $result->row();
            return $row['count'];
        }
    }

    /* file end: ./oc-includes/osclass/classes/database/DAO.php */
?>
